#!/usr/bin/env pwsh

# 个人云笔记 Windows 一键部署脚本
# Personal Cloud Notes Windows Deployment Script
# 版本: 2.0

#Requires -Version 5.1
#Requires -RunAsAdministrator

param(
    [string]$InstallPath = "C:\PersonalCloudNotes",
    [string]$ServiceName = "PersonalCloudNotes",
    [switch]$SkipDependencies = $false,
    [switch]$AutoFix = $false
)

# 全局变量
$Script:InstallPath = $InstallPath
$Script:ServiceName = $ServiceName
$Script:LogFile = "C:\PersonalCloudNotes-Deploy.log"
$Script:BackupDir = "C:\PersonalCloudNotes-Backup"
$Script:DBName = "personal_cloud_notes"
$Script:DBUser = "cloudnotes_user"
$Script:DBPassword = "WJ20240824"
$Script:MySQLRootPassword = "WJ20240824"

# 颜色输出函数
function Write-ColorOutput {
    param(
        [string]$Message,
        [string]$Color = "White"
    )
    
    $colorMap = @{
        "Red" = [ConsoleColor]::Red
        "Green" = [ConsoleColor]::Green
        "Yellow" = [ConsoleColor]::Yellow
        "Blue" = [ConsoleColor]::Blue
        "Cyan" = [ConsoleColor]::Cyan
        "White" = [ConsoleColor]::White
    }
    
    Write-Host $Message -ForegroundColor $colorMap[$Color]
}

# 日志函数
function Write-Log {
    param(
        [string]$Level,
        [string]$Message
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = "[$timestamp] [$Level] $Message"
    
    # 输出到控制台
    switch ($Level) {
        "INFO" { Write-ColorOutput "[$Level] $Message" "Blue" }
        "SUCCESS" { Write-ColorOutput "[$Level] $Message" "Green" }
        "WARNING" { Write-ColorOutput "[$Level] $Message" "Yellow" }
        "ERROR" { Write-ColorOutput "[$Level] $Message" "Red" }
        default { Write-ColorOutput "[$Level] $Message" "White" }
    }
    
    # 写入日志文件
    try {
        $logEntry | Out-File -FilePath $Script:LogFile -Append -Encoding UTF8
    } catch {
        # 忽略日志写入错误
    }
}

# 错误处理函数
function Handle-Error {
    param([string]$ErrorMessage)
    
    Write-Log "ERROR" $ErrorMessage
    
    if ($AutoFix) {
        Write-Log "INFO" "尝试自动修复..."
        return $true
    } else {
        $choice = Read-Host "发生错误，是否继续? (y/n)"
        return $choice -match "^[Yy]"
    }
}

# 检查系统要求
function Test-SystemRequirements {
    Write-Log "INFO" "检查系统要求..."
    
    # 检查Windows版本
    $osVersion = [System.Environment]::OSVersion.Version
    if ($osVersion.Major -lt 10) {
        Handle-Error "需要Windows 10或更高版本"
        return $false
    }
    
    # 检查内存
    $memory = (Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum / 1GB
    if ($memory -lt 2) {
        Write-Log "WARNING" "建议至少4GB内存，当前: ${memory}GB"
    }
    
    # 检查磁盘空间
    $disk = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'"
    $freeSpaceGB = [math]::Round($disk.FreeSpace / 1GB, 2)
    if ($freeSpaceGB -lt 5) {
        Handle-Error "C盘可用空间不足，需要至少5GB，当前: ${freeSpaceGB}GB"
        return $false
    }
    
    Write-Log "SUCCESS" "系统要求检查通过"
    return $true
}

# 安装Chocolatey
function Install-Chocolatey {
    Write-Log "INFO" "安装Chocolatey包管理器..."
    
    try {
        if (Get-Command choco -ErrorAction SilentlyContinue) {
            Write-Log "INFO" "Chocolatey已安装"
            return
        }
        
        Set-ExecutionPolicy Bypass -Scope Process -Force
        Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
        
        # 刷新环境变量
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
        
        Write-Log "SUCCESS" "Chocolatey安装完成"
    } catch {
        Handle-Error "Chocolatey安装失败: $($_.Exception.Message)"
    }
}

# 安装Node.js
function Install-NodeJS {
    Write-Log "INFO" "安装Node.js..."
    
    try {
        if (Get-Command node -ErrorAction SilentlyContinue) {
            $nodeVersion = node --version
            Write-Log "INFO" "Node.js已安装，版本: $nodeVersion"
            return
        }
        
        choco install nodejs -y
        
        # 刷新环境变量
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
        
        # 验证安装
        if (Get-Command node -ErrorAction SilentlyContinue) {
            $nodeVersion = node --version
            Write-Log "SUCCESS" "Node.js安装完成，版本: $nodeVersion"
        } else {
            throw "Node.js安装验证失败"
        }
    } catch {
        Handle-Error "Node.js安装失败: $($_.Exception.Message)"
    }
}

# 安装MySQL
function Install-MySQL {
    Write-Log "INFO" "安装MySQL..."
    
    try {
        if (Get-Command mysql -ErrorAction SilentlyContinue) {
            Write-Log "INFO" "MySQL已安装"
            return
        }
        
        choco install mysql -y
        
        # 启动MySQL服务
        Start-Service -Name MySQL80 -ErrorAction SilentlyContinue
        
        Write-Log "SUCCESS" "MySQL安装完成"
    } catch {
        Handle-Error "MySQL安装失败: $($_.Exception.Message)"
    }
}

# 配置MySQL
function Set-MySQLConfiguration {
    Write-Log "INFO" "配置MySQL..."
    
    try {
        # 设置root密码
        $mysqlCommand = "ALTER USER 'root'@'localhost' IDENTIFIED BY '$Script:MySQLRootPassword'; FLUSH PRIVILEGES;"
        $mysqlCommand | mysql -u root --password="" 2>$null
        
        # 创建数据库和用户
        $createDbCommand = @"
CREATE DATABASE IF NOT EXISTS $Script:DBName CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '$Script:DBUser'@'localhost' IDENTIFIED BY '$Script:DBPassword';
GRANT ALL PRIVILEGES ON $Script:DBName.* TO '$Script:DBUser'@'localhost';
FLUSH PRIVILEGES;
"@
        
        $createDbCommand | mysql -u root -p"$Script:MySQLRootPassword" 2>$null
        
        Write-Log "SUCCESS" "MySQL配置完成"
    } catch {
        Handle-Error "MySQL配置失败: $($_.Exception.Message)"
    }
}

# 部署应用
function Deploy-Application {
    Write-Log "INFO" "部署应用..."
    
    try {
        # 创建安装目录
        if (!(Test-Path $Script:InstallPath)) {
            New-Item -ItemType Directory -Path $Script:InstallPath -Force
        }
        
        # 复制文件
        $sourceDir = Split-Path -Parent $MyInvocation.ScriptName
        Copy-Item -Path "$sourceDir\*" -Destination $Script:InstallPath -Recurse -Force -Exclude "*.ps1"
        
        # 安装依赖
        Set-Location $Script:InstallPath
        npm install --production
        
        # 创建.env文件
        $envContent = @"
NODE_ENV=production
PORT=3000
DB_HOST=localhost
DB_PORT=3306
DB_NAME=$Script:DBName
DB_USER=$Script:DBUser
DB_PASSWORD=$Script:DBPassword
"@
        
        $envContent | Out-File -FilePath ".env" -Encoding UTF8
        
        Write-Log "SUCCESS" "应用部署完成"
    } catch {
        Handle-Error "应用部署失败: $($_.Exception.Message)"
    }
}

# 主函数
function Main {
    Write-ColorOutput "===== 个人云笔记 Windows 部署脚本 =====" "Cyan"
    Write-ColorOutput "版本: 2.0" "Cyan"
    Write-ColorOutput "安装路径: $Script:InstallPath" "Cyan"
    Write-ColorOutput "" "White"
    
    try {
        # 系统检查
        if (!(Test-SystemRequirements)) {
            exit 1
        }
        
        # 安装依赖
        if (!$SkipDependencies) {
            Install-Chocolatey
            Install-NodeJS
            Install-MySQL
        }
        
        # 配置MySQL
        Set-MySQLConfiguration
        
        # 部署应用
        Deploy-Application
        
        Write-Log "SUCCESS" "部署完成！"
        Write-ColorOutput "" "White"
        Write-ColorOutput "🎉 个人云笔记部署成功！" "Green"
        Write-ColorOutput "访问地址: http://localhost:3000" "Green"
        Write-ColorOutput "" "White"
        
    } catch {
        Write-Log "ERROR" "部署失败: $($_.Exception.Message)"
        exit 1
    }
}

# 运行主函数
Main